import { Dep, depsMap } from './dep.mjs';

/**
 * 当前正在运行的 effect
 */
let currentEffect;

function getDep (target, prop) {
  // 从 depsMap 中找到本 target 的 Map
  let deps = depsMap.get(target);
  if (!deps) {
     // 没找到，需要初始化
     deps = new Map();
    depsMap.set(target, deps);
  }
  // 从第二级的 Map 中找到本 prop 的 dep
  let dep = deps.get(prop);
  if (!dep) {
     // 没找到，需要初始化
     dep = new Dep();
    deps.set(prop, dep);
  }
  return dep;
}

export class ReactiveEffect {
	constructor (fn, scheduler) {
		this.fn = fn;
		this.deps = new Set();
		this.active = true;
		this.scheduler = scheduler;
	}
	run () {
		if (!this.active) {
			return this.fn();
		}
		currentEffect = this;
		this.fn();
		currentEffect = null;
	}
	stop() {
		this.active = false;
		for (let dep of this.deps) {
			dep.untrack(this);
		}
		this.deps.clear();
	}
}

/**
 * 创建一个作用函数，并将自动追踪函数内的依赖
 * @param fn 接收的函数
 */
export function effect (fn, scheduler) {
	let e = new ReactiveEffect(fn, scheduler);
	e.run();
	return e;
}

/**
 * 当前正在运行的作用追踪一个依赖
 * @param target 目标对象
 * @param prop 目标对象的属性名
 */
export function track (target, prop) {
	if (!currentEffect) {
		return;
	}
	let dep = getDep(target, prop);
	dep.track(currentEffect);
	currentEffect.deps.add(dep);
}

/**
 * 触发一个依赖下的所有作用
 * @param target 目标对象
 * @param prop 目标对象的属性名
 */
export function trigger (target, prop) {
	depsMap.get(target)?.get(prop)?.trigger();
}
